home *** CD-ROM | disk | FTP | other *** search
- /*
- * MBRESTM - Version 1.61 - 1/20/92
- *
- * Copyright (C) 1988, 1989, 1990, 1991, 1992
- * By the CBBS Group.
- *
- * This program reads the individual message text files and
- * produces MAIL.DAT from the information. It is intended to
- * be used after a mail file crash of version 10.
- *
- * It is expected that this program will be run from the
- * directory containing the message files. The new MAIL.DAT
- * file will also be found in this directory. It will have to
- * copied the the proper bbs directory replacing the corrupted
- * original mail file.
- *
- * MBRESTM when run with any argument will complete itself without
- * any operator intervention. i.e. MBRESTM X
- */
-
- #include "mb.h"
- #ifndef MCH_AMIGA
- #include "dos.h"
- #else
- #include <libraries/dos.h>
- #include <exec/memory.h>
- #include <string.h>
- #include <stdlib.h>
- #endif
-
- MAIL_HDR *mfhs;
- MSG_HDR *tmmhs;
- byte flds;
- char *fld[maxflds];
- char *cmd;
- char *line;
- char *nullstr = "";
-
- #ifndef MCH_AMIGA
- char pp[44], name[1000][13], msgfile[10], badfile[10], temp[6];
- #else
- /* Quick fix for mbrestm on AMIGA. 500 is way too few messages for
- any active BBS to try to recover. Our local system had just over
- 1000 to recover and we're not in a busy QTH! Make it 2000 for now
- and hope it is big enough.
- */
- #define MAXNUM 2000
- char pp[44], name[MAXNUM][13], msgfile[10], badfile[10], temp[5];
- #endif
-
- int count = 0;
- int cmp();
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int x, c, y;
- int xx = 1;
- int recno = 1;
- int msgfl, mail;
- char *t;
-
- mfhs = (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
- tmmhs = (MSG_HDR *) malloc(sizeof(MSG_HDR));
- cmd = (char *) malloc(linelen);
- line = (char *) malloc(linelen);
-
- printf("Mail Restore Program - Version 1.61\n");
- if((mail = open("MAIL.DAT", O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
- { puts("MAIL.DAT cannot be opened - process aborted!\n");
- exit (1);
- }
-
- dir_list();
-
- if (count > MAXNUM)
- {
- printf("Message files greater than %d. Delete some! Aborting\n",MAXNUM);
- exit(1);
- }
- while( xx <= count)
- {
- y = true;
- sprintf (msgfile, "%s",name[xx-1]);
- printf("%s ", msgfile);
- if((msgfl = open( msgfile, O_RDWR | O_BINARY)) < 0)
- {
- printf(" cannot be opened - bypassing this file\n");
- xx++;
- continue;
- }
-
- read_rec(msgfl, 0, (char *) line);
- if(!((line[253] is '\0') and (line[254] is '\r') and (line[255] is '\n')))
- {
- printf(" seems to be corrupted - bypassing this file\n");
- close(msgfl);
- sprintf(badfile, "%s.BAD", msgfile);
- rename(msgfile, badfile);
- xx++;
- continue;
- }
-
- fill(temp, '\0', 6);
- strncpy(temp, &line[0], 5);
- if (atoi(msgfile) != atoi(temp))
- {
- printf("OLD MSG# [%s] -> Renumbered ", temp);
- fill( &line[0], ' ', 5);
- sprintf(&line[0],"%5.5s", msgfile);
- line[5] = ' ';
- write_rec( msgfl, 0, (char*) line);
- }
-
- fill(tmmhs, '\0', 256);
- tmmhs->rn = xx;
- tmmhs->read = atoi( &line[61]);
- tmmhs->number = atoi( &line[0]);
- tmmhs->size = atoi( &line[9]);
- tmmhs->type = line[6];
- switch (line[7])
- {
- case 'O': tmmhs->stat = m_stale; break;
- case 'F': tmmhs->stat = m_fwd; break;
- case 'H': tmmhs->stat = m_hold; break;
- case 'Y': tmmhs->stat = m_read; break;
- case 'K': tmmhs->stat = m_kill; break;
- case 'B': tmmhs->stat = m_busy; break;
- case '$': tmmhs->stat = m_bull; break;
- default: tmmhs->stat = '\0';
- }
-
- strncpy(tmmhs->to, &line[15], ln_call);
- strncpy(tmmhs->from, &line[22], ln_call);
- strncpy(tmmhs->bbs, &line[29],ln_call);
- strncpy(tmmhs->date, &line[36], ln_date);
- strncpy(tmmhs->time, &line[43], ln_time);
- #ifdef MCH_AMIGA
- /* Recover the lifetime */
- tmmhs->lifetime = line[252];
- #endif
- fill(tmmhs->bid, ' ', ln_bid);
- if (line[48] isnt ' ') unbl(tmmhs->bid, &line[48], ln_bid);
- tmmhs->ext = line[68] - '0';
- if (tmmhs->ext is 1)
- {
- #ifndef MCH_AMIGA
- strncpy(tmmhs->flag, &line[70], mmesn);
- #else
- strncpy((char *)tmmhs->flag, &line[70], mmesn);
- #endif
- for( x=0, c=0; x < mmesn; x++, c++)
- {
- if (tmmhs->flag[x] is ' ') { tmmhs->flag[x] = '0'; c--;}
- tmmhs->flag[x] = (tmmhs->flag[x]-'0');
- }
- tmmhs->count = c;
- y = dodis();
- }
- if (tmmhs->ext is 2)
- {
- strcpy (cmd, &line[70]);
- remnl (cmd);
- strcpy(tmmhs->call[0], cmd);
- t = strchr(&line[68], '\n');
- t++;
- strcpy(cmd, t);
- remnl(cmd);
- strcpy(tmmhs->title, cmd);
- }
- else
- {
- parse();
- strcpy(tmmhs->title, fld[0]);
- }
- write_rec(mail,recno++,(char *)tmmhs);
- close(msgfl);
- if (y) puts("restored");
- xx++;
- }
- mfhs->next = recno;
- mfhs->first = 1;
- mfhs->last = recno-1;
- mfhs->version = mb_version;
- mfhs->free = 0;
- mfhs->count = recno-1;
- mfhs->unt_msg = 1;
- fill(mfhs->unu, '\0', mfhsunu);
- fill(mfhs->date, '\0', ln_date);
- fill(mfhs->time, '\0', ln_time);
- x = 1;
- if (count) x = 1 + atoi(name[count - 1]);
- printf("The next message number will be %u\n", x);
- *cmd = 0;
- if (argc < 2)
- {
- printf("Enter return if OK or new message number ");
- gets(cmd);
-
- }
- if (*cmd) mfhs->next_msg = atoi(cmd);
- else mfhs->next_msg = x;
- mfhs->unt_msg = mfhs->next_msg;
- write_rec(mail, 0, (char *)mfhs);
-
- close(mail);
- }
-
- /*
- * Parse a command line.
- *
- * Input: Line of text in line.
- * Returns: Fields are placed in cmd.
- * Fields are pointed to by fld[].
- * flds is set to the number of fields found.
- * Each field is null-terminated.
- * Fields beyond maxflds are ignored.
- */
-
- parse()
- {
- char skip;
- register short bl;
- register char *in, *out;
-
- for (flds = 0; flds < maxflds;)
- fld[flds++] = nullstr;
-
- in = &line[86];
- out = cmd;
- bl = false;
- flds = 0;
- skip = true;
-
- while (*in and (flds < maxflds) and (out < (cmd + linelen - 1)))
- {
- #ifndef MCH_AMIGA
- if (*in is '\r') { *in++; continue;}
- #else
- /* Work around a bug in MANX 5.0d compiler (and what a bug!)
- The *in++ does not increment in, so as soon as the program finds
- a '\r' it hangs in an infinite loop!
- */
- if (*in is '\r') { in++; continue;}
- #endif
- if (*in is '\n') skip = !(skip);
- *out = *in;
- if (bl) {if ((*in <= ' ') and (skip)) { bl = false; *out = '\0'; } out++; }
- else {if (*in > ' ') { bl = true; fld[flds++] = out++; }}
- in++;
- }
- *out = '\0';
- }
-
-
- /*
- * Remove new line and carriage returns from end of string.
- */
-
- remnl(p)
- char *p;
- {
- for (; *p; p++)
- {
- if ((*p is '\n') or (*p is '\r')) { *p = '\0'; return; }
- }
- }
- /*
- * Read random record.
- */
-
- read_rec(fid, rec, buffer)
- int fid;
- int rec;
- char buffer[];
- {
- #ifndef MCH_AMIGA
- long lseek();
- #endif
- long offs;
-
- offs = (long)rec * (long)RECSIZE;
- lseek(fid, offs, 0);
- return (read(fid, buffer, RECSIZE) is RECSIZE);
- }
-
- /*
- * Write random record.
- */
-
- write_rec(fid, rec, buffer)
- int fid;
- int rec;
- char buffer[];
- {
- #ifndef MCH_AMIGA
- long lseek();
- #endif
- long offs;
-
- offs = (long)rec * (long)RECSIZE;
- lseek(fid, offs, 0);
- return (write(fid, buffer, RECSIZE) is RECSIZE);
- }
- /*
- * Fill some memory with a character.
- */
-
- fill(adr, ch, len)
- char *adr;
- char ch;
- int len;
- {
- while (len--) *adr++ = ch;
- }
-
- /*
- * Create the distribution list, if required.
- */
-
- dodis()
- {
- register FILE *dfl;
- char c;
- char tmp[linelen];
-
- tmmhs->ext = 0;
- if (*tmmhs->bbs is ' ') return;
- unbl(tmp, tmmhs->bbs, ln_call);
- strcat( tmp, ".DIS");
-
- if ((dfl = fopen( tmp, "r")) is NULL)
- {
- printf("restored without %s (file is not found)\n", tmp);
- return false;
- }
- tmmhs->ext = 0x01;
-
- for (c = 0; (c <tmmhs->count) and (fgets( tmp, linelen, dfl) isnt NULL);
- c++)
- {
- strupr(tmp);
- pcall(tmmhs->call[c], tmp);
- }
- fclose(dfl);
- return true;
- }
- /*
- * Copy LJSF string to C string.
- */
-
- unbl(to, from, size)
- char *to, *from;
- int size;
- {
- while (size--)
- {
- if (*from <= ' ') { *to = '\0'; return; }
- *to++ = *from++;
- }
- *to = '\0';
- }
- /*
- * Parse a callsign.
- * Blank pad the output field, remove trailing ssid from call.
- * Return the SSID.
- */
-
- pcall(c, p)
- char *c;
- char *p;
- {
- register short i;
-
- /*
- * Blank fill the target buffer.
- */
-
- fill (c, ' ', ln_call);
-
- /*
- * Ignore leading spaces.
- */
-
- while (*p and (*p is ' ')) p++;
-
- /*
- * Copy the call from the string into the call buffer.
- */
-
- for (i = ln_call; i and *p; i--)
- {
- if (*p <= ' ') return 0;
- if (*p is '-') return atoi(++p);
- *c++ = *p++;
- }
- if (*p++ is '-') return atoi(p); else return 0;
- }
-
- /*
- * Read the file names from the current directory and store
- * the results in an array but exclude any name that is not
- * made up of all numbers.
- * Sort the resulting list in ascending order.
- */
-
- #ifndef MCH_AMIGA
- dir_list()
- {
- int x, y;
- char *file_name = "*.";
-
- printf("Reading directory - ");
- bdos(0x1a, (unsigned)pp, 0);
- if(18==bdos(0x4e, (unsigned)file_name, 0))
- {
- printf("No message files are found\n");
- return;
- }
-
- if (num( &pp[30])) strcpy (name[count++], &pp[30]);
-
- for(;;)
- {
- if(18==bdos(0x4f, 0, 0)) break;
- if (num( &pp[30])) strcpy (name[count++], &pp[30]);
- }
- #else
- /*
- * A directory item looks like this:
- struct FileInfoBlock {
- LONG fib_DiskKey;
- LONG fib_DirEntryType;
- char fib_FileName[108];
- LONG fib_Protection;
- LONG fib_EntryType;
- LONG fib_Size;
- LONG fib_NumBlocks;
- struct DateStamp fib_Date;
- char fib_Comment[80];
- char padding[36];
- };
- */
-
- typedef struct FileInfoBlock FCB;
-
- static FCB *fcb = 0;
-
- /*
- * Open directory and create list of numeric files.
- */
- long lock;
- extern long Examine(),Lock(),ExNext();
- dir_list()
- {
- int x, y;
- long result,Info();
- fcb = (FCB *)AllocMem((long)sizeof(*fcb),MEMF_PUBLIC|MEMF_CLEAR);
- /*
- * Get a lock on the current directory
- */
- lock = Lock((UBYTE *)"",ACCESS_READ);
- if(lock == 0L) {
- return;
- }
- /* and examine it to make sure it's OK */
- if((result = Examine(lock,fcb)) == 0L) {
- UnLock(lock);
- return;
- }
- for(;;) {
- /* Get next directory entry */
- if(ExNext(lock,fcb) == 0L) {
- UnLock(lock);
- break;
- }
- /* If the entry is a directory, go back for another */
- if(fcb->fib_DirEntryType > 0)continue;
- /* If the filename is numeric then add it into the list */
- if(num(fcb->fib_FileName)) {
- strcpy (name[count++], &fcb->fib_FileName[0]);
- if(count >= MAXNUM) {
- printf("Sorry - I can't handle more than %d entries\n",MAXNUM);
- printf("Try deleting some of the older message numbers\n");
- printf("manually and then try mbrestm again\n");
- UnLock(lock);
- FreeMem(fcb,(long)sizeof(*fcb));
- exit(1);
- }
- }
- }
- FreeMem(fcb,(long)sizeof(*fcb));
- #endif
- printf("There are %d message files\n", count);
- if (count)
- {
- printf("***Sorting***\n");
- qsort (name, count, 13, cmp);
- for(x=0, y=1; x< count; x++, y++)
- {
- printf("%6s", name[x]);
- if(y is 10) { printf("\n"); y=0; }
- }
- printf("\n");
- }
- }
-
- /*
- * Compare two strings converted to integers.
- */
-
- int cmp(n1,n2)
- char *n1;
- char *n2;
- {
- return (atoi(n1) - atoi(n2));
-
- }
-
- /*
- * Is the string a number?
- */
-
- num(p)
- char *p;
- {
- for (; *p; p++) if (!isdigit(*p)) return false;
- return true;
- }
-
-